package com.pe.utils;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.reflect.TypeToken;

public class GsonUtil {
	
    @SuppressWarnings("unchecked")
	private static class Deserializer implements JsonDeserializer {

        @Override
        public Object deserialize(JsonElement json, Type typeofT, JsonDeserializationContext context) throws JsonParseException {
            Object result = null;
            if (json.isJsonNull()) {
                result = null;
            } else if (json.isJsonPrimitive()) {
                result = json.getAsString();
            } else if (json.isJsonArray()) {
                JsonArray jsonArray = json.getAsJsonArray();
                result = new ArrayList(jsonArray.size());
                for (JsonElement element : jsonArray) {
                    Object object = deserialize(element, typeofT, context);
                    ((List)result).add(object);
                }
            } else if (json.isJsonObject()) {
                JsonObject jsonObj = json.getAsJsonObject();
                result = new HashMap();
                for (Map.Entry<String, JsonElement> entry : jsonObj.entrySet()) {
                    String key = entry.getKey();
                    JsonElement element = entry.getValue();
                    Object object = deserialize(element, typeofT, context);
                    ((Map)result).put(key, object);
                }
            }
            return result;
        }
    }

    // TODO: Use Deserializer and remove this
    @SuppressWarnings({ "unused", "unchecked" })
	private static class HashMapDeserializer implements JsonDeserializer<HashMap> {

        @Override
        public HashMap deserialize(JsonElement json, Type typeofT, JsonDeserializationContext context) throws JsonParseException {
            JsonObject jsonObj = json.getAsJsonObject();
            HashMap map = new HashMap();
            for (Map.Entry<String, JsonElement> entry : jsonObj.entrySet()) {
                String key = entry.getKey();
                JsonElement valueElem = entry.getValue();
                Object value = extractValue(valueElem, typeofT, context);
                map.put(key, value);
            }
            return map;
        }

        private Object extractValue(JsonElement valueElem, Type typeofT, JsonDeserializationContext context) {
            Object value = null;
            if (valueElem.isJsonPrimitive()) {
                value = valueElem.getAsString();
            } else if (valueElem.isJsonArray()) {
                JsonArray arr = valueElem.getAsJsonArray();
                ArrayList list = new ArrayList(arr.size());
                for (JsonElement jsonElement : arr) {
                    Object object = extractValue(jsonElement, typeofT, context);
                    list.add(object);
                }
                value = list;
            } else if (valueElem.isJsonNull()) {
                value = null;
            } else if (valueElem.isJsonObject()) {
                value = deserialize(valueElem.getAsJsonObject(), typeofT, context);
            }
            return value;
        }
    }
	  public static String serializeObjectToJson(Object object) {
	        Gson gson = new Gson();
	        String jsonStr = new GsonPrettyPrinter(gson).ppJson(object);
	        return jsonStr;
	    }
	  
	  @SuppressWarnings("unchecked")
	public static  Map fromJson(String json) {
	        try {
	            Type collectionType = new TypeToken<HashMap>() {
	            }.getType();
	            GsonBuilder gson = new GsonBuilder();
	            // gson.registerTypeAdapter(HashMap.class, new HashMapDeserializer());
	            gson.registerTypeAdapter(HashMap.class, new Deserializer());
	            Gson gsonP = gson.create();
	            Map data = gsonP.fromJson(json, collectionType);
	            return data;
	        } catch (JsonParseException e) {
	            throw e;
	        }
	    }

	    @SuppressWarnings("unchecked")
		public static List fromJsonList(String json) {
	        Type collectionType = new TypeToken<ArrayList>() {
	        }.getType();
	        GsonBuilder gson = new GsonBuilder();
	        gson.registerTypeAdapter(ArrayList.class, new Deserializer());
	        Gson gsonP = gson.create();
	        List data = gsonP.fromJson(json, collectionType);
	        return data;

	    }
	  
}
